{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " # Interacting with `sympy`\n",
    " \n",
    "`pymbolic` can help take care of many *structural* transformations on your expression trees with great ease. Its main purpose is to help with program transformation after all, not to be a full computer algebra system. That said, if you need a full computer algebra system for things like calculus and simplification, it's easy to get your expressions converted between `pymbolic` and `sympy`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/lib/python3/dist-packages/sympy/core/function.py:105: DeprecationWarning: inspect.getargspec() is deprecated, use inspect.signature() instead\n",
      "  evalargspec = inspect.getargspec(cls.eval)\n"
     ]
    }
   ],
   "source": [
    "import sympy as sp\n",
    "from pymbolic import var\n",
    "\n",
    "x = var(\"x\")\n",
    "y = var(\"y\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(x**2 + 2*x + 1) / (x**2 + x)\n"
     ]
    }
   ],
   "source": [
    "expr = (x**2 + 2*x + 1)/(x**2 + x)\n",
    "print(expr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's import pymbolic's sympy interoperability code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# pymbolic.interop.sympy in newer versions of pymbolic\n",
    "from pymbolic.sympy_interface import (\n",
    "    PymbolicToSympyMapper, SympyToPymbolicMapper)\n",
    "\n",
    "p2s = PymbolicToSympyMapper()\n",
    "s2p = SympyToPymbolicMapper()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(x**2 + 2*x + 1)/(x**2 + x)\n"
     ]
    }
   ],
   "source": [
    "sympy_expr = p2s(expr)\n",
    "print(sympy_expr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(x + 1)/x\n"
     ]
    }
   ],
   "source": [
    "sympy_result = sp.cancel(sympy_expr)\n",
    "print(sympy_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x**(-1)*(1 + x)\n"
     ]
    }
   ],
   "source": [
    "result = s2p(sympy_result)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One thing to note is that `PymbolicToSympyMapper` is a regular `pymbolic` mapper, and its behavior can be overridden in case something about the translation to sympy is not quite what you want.\n",
    "\n",
    "`SympyToPymbolicMapper` also behaves very similarly (and can be overridden similarly) although it is not entirely the same kind of mapper."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.0+"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
